/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
 * secGear is licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <stdio.h>
#include <string.h>
#include <vector>
#include "nested_t.h"

#define TA_HELLO_WORLD        "secgear hello world!"
#define BUF_MAX 32


#define ADD 1
#define SUB 2
#define MUL 3
#define DIV 4
#define EXP 5
#define SEND 6
#define RECIEVE 7

//内部飞地定义
class subEnclave {
	private:
		int subEnlaveID;
		int tag;
		double result;
		double rev;
	public:
		subEnclave();
		int setID(int);
		int setTag(int);
		double add(double, double);
		double sub(double, double);
		double mul(double, double);
		double div(double, double);
		double exp(double);
		int get_tag();
		int get_id();
		friend int send(subEnclave &, subEnclave &);
		friend int recieve(subEnclave &, subEnclave &);
		~subEnclave();
};

subEnclave::subEnclave() {
	subEnlaveID = 0;
	tag = 0;
	result = 0;
	rev = 0;
	//cout << "create subenclave success" << endl;
	
}

subEnclave vec[100];

int subEnclave::setID(int ID) {
	this->subEnlaveID = ID;
	return 0;
}

int subEnclave::setTag(int tag) {
	this->tag = tag;
	return 0;
}

double subEnclave::add(double a = 20, double b = 10) {
	result = a + b;
	return result;
}

double subEnclave::sub(double a = 20, double b = 10) {
	result = a - b;
	return result;
}

double subEnclave::mul(double a = 20, double b = 10) {
	result = a * b;
	return result;
}

double subEnclave::div(double a = 20, double b = 10) {
	result = a / b;
	return result;
}

double subEnclave::exp(double x = 7) {
	result = x * x + 2 * x + 1;
	return result;
}

int subEnclave::get_tag() {
	return tag;
}

int subEnclave::get_id() {
	return subEnlaveID;
}

int send(subEnclave &a, subEnclave &b) {
	b.rev = a.result;
	return 0;
}

int recieve(subEnclave &a, subEnclave &b) {
	a.rev = b.result;
	return 0;
}

subEnclave::~subEnclave() {
	//cout << "destroy subenclave success" << endl;
	print_destroy();
}

//////////////////////////////////////////////


//std::vector<subEnclave> vec;



// create
int createSubEnclave(int id)
{
	
	vec[id].setID(id);
	print_create();
	//vec.push_back(se[i]);
	return 0;
}

// destroy
int destroySubEnclave()
{
	print_destroy();
	//vec.push_back(se[i]);
	return 0;
}

/*
int isExist(int ID,int num) 
{
	int sub = -1;
	
    for (int i = 0; i < size; i++) {
			if (ID == arr[i].get_id()) {
				sub = i;
				break;
			}
		}
	
	for (int i = 0; i < num; i++) {
		if (ID == vec[i].get_id()) {
			sub = i;
			break;
		}
	}
}
*/

//飞地内计算(ecall)
int compute(int tag, int size, int sub, double* result) {
	int ID[2];
	int sub1;
	vec[sub].setTag(tag);
	if (tag == ADD) {
		// cout << "result:" << arr[sub].add() << endl;
        print_res(vec[sub].add());
        result[0] = vec[sub].add();
    } else if (tag == SUB) {
		//cout << "result:" << arr[sub].sub() << endl;
		print_res(vec[sub].sub());
        result[0] = vec[sub].sub();
	} else if (tag == MUL) {
		//cout << "result:" << arr[sub].mul() << endl;
		print_res(vec[sub].mul());
        result[0] = vec[sub].mul();
	} else if (tag == DIV) {
		//cout << "result:" << arr[sub].div() << endl;
		print_res(vec[sub].div());
        result[0] = vec[sub].div();
	} else if (tag == EXP) {
		//cout << "result:" << arr[sub].exp() << endl;
		print_res(vec[sub].exp());
        result[0] = vec[sub].exp();
	} else if (tag == SEND) {
		//cout << "Please enter the subEnclaveID of the recipient:";
		print_send_hit();
		while (1) {
			sub1 = -1;
			getid(ID);
			for (int i = 0; i < size; i++) {
				if (ID[0] == vec[i].get_id()) {
					sub1 = i;
					break;
				}
			}
			if (sub1 == -1) {
				//cout << "The subEnclaveID was not found,please re-enter:";
				print_reenter_hit();
				continue;
			} else
				break;
		}
		send(vec[sub], vec[sub1]);
		//cout << "Send Success!" << endl;
		print_send();
	} else if (tag == RECIEVE) {
		//cout << "Please enter the subEnclaveID of the Sender:";
		print_recieve_hit();
		while (1) {
			sub1 = -1;
			//cin >> ID;
			getid(ID);
			for (int i = 0; i < size; i++) {
				if (ID[0] == vec[i].get_id()) {
					sub1 = i;
					break;
				}
			}
			if (sub1 == -1) {
				//cout << "The subEnclaveID was not found,please re-enter:";
				print_reenter_hit();
				continue;
			} else
				break;
		}
		recieve(vec[sub], vec[sub1]);
		//cout << "Recieve Success!" << endl;
		print_recieve();
	} else {
		print_error();
	}
	return 0;
}

